package org.sgroup.imenu.service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class ObjectMapper {
	
	private static final String CSV_TABLE_SEPARATOR = "\n###\n";
	private static final String CSV_LINE_SEPARATOR="\n";
	private static final String CSV_FIELD_SEPARATOR=",";
	/* Convert CSV to List Object
	 * Sample call: see Category.java
	 * List<Category> cats = ObjectMapper.CSVToObject(csvData, Category.class);
	 */
	public static <T> List<T> CSVToObject(String csvData,Class<T> c)
	{
		return CSVToObject(csvData,c,0);
	}
	/*
	 * List<Category> cats = ObjectMapper.CSVToObject(csvData, Category.class,0);
	 */
	public static <T> List<T> CSVToObject(String csvData,Class<T> c,int tableIndex)
	{
		List<T> list = new ArrayList<T>();
		List<List<String>> data = CSVToStringArray(csvData, tableIndex);
		
		if(data ==null) return null;
		if(data.size()<=1) return null;
		
		try{
			for(int i = 1;i < data.size(); i++)
			{
				T obj = c.newInstance();
				for(int j=0;j< data.get(0).size();j++)
				{
					SetPropertiesValue(obj,c,data.get(0).get(j),data.get(i).get(j));
				}
				list.add(obj);
			}
		}
		catch (Exception e) {
			// TODO: handle exception
		}
		return list;
	}
	
	private static List<List<String>> CSVToStringArray(String csvData, int tableIndex )
	{
		//Neu du lieu rong
		if(csvData =="") return null;
		String[] tables = csvData.split(CSV_TABLE_SEPARATOR); 
		//Neu table muon lay khong dung
		if(tableIndex >= tables.length || tableIndex < 0) return null;	
		
		//Neu du lieu rong
		if(tables[tableIndex] =="") return null;
		String[] lines = tables[tableIndex].split(CSV_LINE_SEPARATOR);
		if(lines.length <=1) return null;
		
		List<List<String>> array = new ArrayList<List<String>>();
		//array.add(headers);
		for(int i=0 ;i< lines.length ;i++)
		{
			array.add(ParseCsvRow(lines[i]));// lines[i].split(CSV_FIELD_SEPARATOR));
		}
		return array;
	}

	private static <T> void SetPropertiesValue(Object target,Class<T> c,String propertiesName,Object value)
	{
		try{
			
			Field f = c.getField(propertiesName);
			if(f ==null) return;
			
			if(f.getType()== String.class)
			{
				f.set(target, value);
			}
			else if(f.getType() == int.class)
			{
				f.setInt(target, Integer.parseInt(value.toString()));
			}
			else if(f.getType() == boolean.class)
			{
				f.setBoolean(target, Boolean.parseBoolean(value.toString()));
			}
			else if(f.getType() == float.class)
			{
				f.setFloat(target, Float.parseFloat(value.toString()));
			}
			else if(f.getType() == double.class)
			{
				f.setDouble(target, Double.parseDouble(value.toString()));
			}
			
		}
		catch(Exception ex)
		{
			
		}
	}

	private static List<String> ParseCsvRow(String line)
    {

        String[] c;
        List<String> resp = new ArrayList<String>();
        boolean cont = false;
        String cs = "";

        c = line.split( CSV_FIELD_SEPARATOR );

        for(int i=0;i<c.length;i++)// each (String y in c)
        {
        	String x = c[i];


            if (cont)
            {
                // End of field
                if (x.endsWith("\""))
                {
                    cs += CSV_FIELD_SEPARATOR + x.substring(0, x.length() - 1);
                    resp.add(cs);
                    cs = "";
                    cont = false;
                    continue;

                }
                else
                {
                    // Field still not ended
                    cs += CSV_FIELD_SEPARATOR + x;
                    continue;
                }
            }

            // Fully encapsulated with no comma within
            if (x.startsWith("\"") && x.endsWith("\""))
            {
                if ((x.endsWith("\"\"") && !x.endsWith("\"\"\"")) && !x.equalsIgnoreCase("\"\""))
                {
                    cont = true;
                    //boolean a= x.equalsIgnoreCase("\"\"");
                    cs = x;
                    continue;
                }

                resp.add(x.substring(1, x.length() - 1));
                continue;
            }

            // Start of encapsulation but comma has split it into at least next field
            if (x.startsWith("\"") && !x.endsWith("\""))
            {
                cont = true;
                cs += x.substring(1);
                continue;
            }

            // Non encapsulated complete field
            resp.add(x);

        }

        return resp;

    }
}
